//#pragma once
#ifndef __HLS__
#define __HLS__

#include <set>
#include <map>
#include "Graph.h"

using namespace std;

enum listorder {byasap = 1, byalap = 2};

bool isResourceAvailable ( int step, type t, int delay );
bool isResourceAvailable ( int core, int step, type t, int delay );

int lowBound ( Operation * op );
int lowBound ( int core, Operation * op );

void updateALAP ( Operation * op1 );
void updateALAP ( int core, Operation * op, bool shrink );
void updateASAP ( Operation* op, int step );
void updateASAP ( int core, Operation* op, int step );
void initASAP();
void initALAP();

bool isPrecedence ( Operation * op1, int step );
bool isPrecedence ( int core, Operation * op1, int step );
bool isPrecedence ( Operation * op, int step, map<int, int> schedule );

bool levelBound ( Operation * op );
bool levelBound ( int core, Operation * op, int step );

void addSink ( Operation * op, Graph * graph ); // f
Graph *getSubGraph ( Operation * op ); // f
Graph * getReversedGraph ( Graph * graph ); // f
int getCriticalPathLength ( Operation * op, Graph * g, enum cptype type ); // f
Graph *getPrecedenceGraph ( Operation * op, Graph * base );
int DFS ( Graph * g,  set<int> * rs, Operation * op, int depth, enum cptype type, bool isSimple );
void DFS ( Operation * op, int depth );  // f

void branchBoundRCS ( int i, bool updateALAP, bool CPbound, bool levelBound );
void branchBoundRCS_h ( int i );
void  branchBoundRCS_thread ( void* arg );
void occupyResource ( int step, type t, int delay );
void releaseResource ( int step, type t, int delay );
void occupyResource ( int core, int step, type t, int delay );
void releaseResource ( int core, int step, type t, int delay );
int calculateMaxScheduleTime();
int calculateMaxScheduleTime ( int core );

void getLhHh ( int * l, int * h, Operation * op );
set<Operation *> getImmediatePrecedent ( Operation * op );

void initOptimalSchedule();
void basicEnu ( int i );
void listSchedule();
void listSchedule ( listorder lo );
void floydWarshall();

int upperBound ( Operation * op );
unsigned long long GetCycleCount();

struct thread_ag;
struct search_ag;
void  coreScheduler ( void * arg );
bool topoBound ( Operation * op );

void testDriver ( char * info, bool shrink, bool low, bool level, bool twophase );
void parallelTestDriver ( void * arg );

void resetContext();
void printInfo ( char * str );
bool isResourceEqual ( int core, int step, type t, int delay );

void topoSort();

void validateSchedule ( map<Operation*, int> Schedule, map < type, map < int, int > > resources );

//--------------
int compute_lower_bound();
int compute_asapuc ( Operation* op );
void compute_alapuc ( set<Operation *> R, int CP );
int greedy_lower_bound ( set<Operation*> R, int CP );
int recursive_lower_bound ( Operation* op );
int compute_critical_path ( Operation* op );

#endif
